package org.jeecg.modules.message.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.lottery.entity.LotteryManagement;
import org.jeecg.modules.lottery.service.ILotteryManagementService;
import org.jeecg.modules.message.WebSocket.WebSocketServer;
import org.jeecg.modules.message.entity.ProcurementMessage;
import org.jeecg.modules.message.mapper.ProcurementMessageMapper;
import org.jeecg.modules.message.service.IProcurementMessageService;
import org.jeecg.modules.supplier.entity.ProcUserSupplierRelation;
import org.jeecg.modules.supplier.service.IProcUserSupplierRelationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class ProcurementMessageServiceImpl extends ServiceImpl<ProcurementMessageMapper, ProcurementMessage> implements IProcurementMessageService {

    @Autowired
    private ProcurementMessageMapper procurementMessageMapper;

    @Autowired
    private IProcUserSupplierRelationService procUserSupplierRelationService;
    @Autowired
    private ILotteryManagementService lotteryManagementService;


    /**
     * 根据接收人获取未读消息
     *
     * @param receiverId 接收人ID
     * @return 未读消息列表
     */

    public List<ProcurementMessage> getUnreadMessages(String receiverId,String readStatus) {
        // 参数校验，参数不为空
        if (StringUtils.isBlank(receiverId)) {
            throw new IllegalArgumentException("参数不能为空");
        }

        // 使用QueryWrapper构建查询条件
        com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<ProcurementMessage> queryWrapper = new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
        queryWrapper.eq("read_status", readStatus) // 0表示未读
                .eq("is_deleted", "0"); // 0表示未删除

        // 接收人ID条件
        if (StringUtils.isNotBlank(receiverId)) {
            // 如果参数不为空，则匹配
            queryWrapper.eq("receiver_id", receiverId);
        }

        // 按创建时间降序排列
        queryWrapper.orderByDesc("create_time");

        return this.list(queryWrapper);
    }

    /**
     * 根据业务类型和业务ID获取消息
     *
     * @param businessType 业务类型
     * @param businessId   业务ID
     * @return 消息列表
     */
    @Override
    public List<ProcurementMessage> getMessagesByBusiness(String businessType, String businessId) {
        if (StringUtils.isAnyBlank(businessType, businessId)) {
            return new ArrayList<>();
        }
        return procurementMessageMapper.getMessagesByBusiness(businessType, businessId);
    }

    @Override
    @Transactional //消息存在，更新其阅读状态，并在状态为“已读”时记录阅读时间
    public boolean updateReadStatus(String messageId, String readStatus) {
        if (StringUtils.isAnyBlank(messageId, readStatus)) {
            return false;
        }
        ProcurementMessage message = this.getById(messageId);
        if (message == null) {
            log.error("消息不存在: {}", messageId);
            return false;
        }
        message.setReadStatus(readStatus);

        message.setReadTime(new Date());

        return this.updateById(message);
    }

    /**
     * 批量更新消息阅读状态 标记已读
     *
     * @param messageIds 消息ID列表
     * @param readStatus 阅读状态
     * @return 更新数量
     */
    @Override
    @Transactional
    public boolean batchUpdateReadStatus(List<String> messageIds, String readStatus) {
        if (messageIds == null || messageIds.isEmpty() || StringUtils.isBlank(readStatus)) {
            return false;
        }
        Date readTime = new Date();
        int updateCount = procurementMessageMapper.batchUpdateReadStatus(messageIds, readStatus, readTime);
        return updateCount > 0;
    }


    @Transactional//采购构造通知的标题和内容，根据审核状态和审核意见动态生成内容
    public boolean sendPurchasePlanNotice(String purchaseId, String Title, String auditStatus,
                                          String auditOpinion, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(purchaseId, Title, auditStatus)) {
            return false;//检查多个字符串中是否有任何一个为空或空白
        }
        String title = "采购计划审核通知";
        String content = String.format("您的采购计划 '%s' 已被%s", Title,
                "1".equals(auditStatus) ? "审核通过" : "退回");
        if (StringUtils.isNotBlank(auditOpinion)) {
            content += String.format("，审核意见：%s", auditOpinion);
        }
        //实现两端互联
        return sendMessage(title, content, "1", "purchase", purchaseId, receiverId, receiver);
    }

    //供应商构造通知的标题和内容，根据审核状态和审核意见动态生成内容
    @Transactional
    public boolean sendSupplierAuditNotice(String supplierId, String supplierName, String auditStatus,
                                           String auditOpinion, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(supplierId, supplierName, auditStatus)) {
            return false;
        }
        String title = "供应商审核通知";
        String content = String.format("您的供应商 '%s' 已被%s", supplierName,
                "1".equals(auditStatus) ? "审核通过" : "退回");
        if (StringUtils.isNotBlank(auditOpinion)) {
            content += String.format("，审核意见：%s", auditOpinion);
        }
        //根据businessId也就是proc_user_supplier中的supplier_id查找对应的username、
        return sendMessage(title, content, "1", "supplier", supplierId, receiverId, receiver);
    }

    /**
     * 发送投标通知
     *
     * @param bidId      投标ID
     * @param bidTitle   投标标题
     * @param bidType    投标类型
     * @param receiverId 接收人ID
     * @return 是否成功
     */

    @Transactional
    public boolean sendBidNotice(String bidId, String bidTitle, String bidType, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(bidId, bidTitle, receiverId)) {
            return false;
        }
        String title = "投标通知";
        String content = String.format("有新的%s项目 '%s' 开始招标，请及时关注！",
                getBidTypeName(bidType), bidTitle);
        return sendMessage(title, content, "3", "bid", bidId, receiverId, receiver);
    }

    @Override
    @Transactional
    public boolean sendBidOpeningNotice(String bidId, String bidTitle, String openTime, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(bidId, bidTitle, openTime)) {
            return false;
        }
        String title = "开标通知";
        String content = String.format("项目 '%s' 将于%s开始开标，请准时参加！", bidTitle, openTime);
        return sendMessage(title, content, "3", "bid", bidId, receiverId, receiver);
    }

    /**
     * 发送中标通知
     *
     * @param bidId      投标ID
     * @param projectName   投标项目名
     * @param receiverId 接收人ID
     * @return 是否成功
     */
    @Override
    @Transactional
    public boolean sendWinningResultNotice(String bidId, String projectName, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(bidId, projectName, receiverId)) {
            return false;
        }
        String title = "中标结果通知";
        String content = String.format("项目 '%s' 的中标结果已公布,恭喜您中标", projectName);
        return sendMessage(title, content, "3", "bid", bidId, receiverId, receiver);
    }

    /**
     * 发送流标通知
     *
     * @param bidId      投标ID
     * @param bidTitle   投标标题
     * @param reason     流标原因
     * @param receiverId 接收人ID
     * @return 是否成功
     */
    @Override
    @Transactional
    public boolean sendBidFailureNotice(String bidId, String bidTitle, String reason, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(bidId, bidTitle, receiverId)) {
            return false;
        }
        String title = "流标通知";
        String content = String.format("项目 '%s' 已流标", bidTitle);
        if (StringUtils.isNotBlank(reason)) {
            content += String.format("，原因：%s", reason);
        }
        return sendMessage(title, content, "3", "bid", bidId, receiverId, receiver);
    }

    /**
     * 发送投标即将截止提醒
     *
     * @param bidId        投标ID
     * @param ProjectName     投标项目
     * @param deadlineTime 截止时间
     * @param receiverId   接收人ID
     * @return 是否成功
     */
    @Override
    @Transactional
    public boolean sendBiddingDeadlineReminder(String bidId, String ProjectName, String deadlineTime, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(bidId, ProjectName, deadlineTime, receiverId)) {
            return false;
        }

        String title = "投标即将截止提醒";
        String content = String.format("项目 '%s' 的投标将于%s截止，请及时提交投标文件！", ProjectName, deadlineTime);
        return sendMessage(title, content, "3", "bid", bidId, receiverId, receiver);
    }

    /**
     * 发送投标已截止提醒
     *
     * @param bidId        投标ID
     * @param bidTitle     投标标题
     * @param deadlineTime 截止时间
     * @param receiverId   接收人ID
     * @return 是否成功
     */
    @Override
    @Transactional
    public boolean afSendBiddingDeadlineReminder(String bidId, String bidTitle, String deadlineTime, String receiverId, String receiver) {
        if (StringUtils.isAnyBlank(bidId, bidTitle, deadlineTime, receiverId)) {
            return false;
        }
        String title = "投标已截止提醒";
        String content = String.format("项目 '%s' 的投标将于%s截止，请及时提交投标文件！", bidTitle, deadlineTime);
        return sendMessage(title, content, "3", "bid", bidId, receiverId, receiver);
    }

    /**
     * 批量发送投标即将截止提醒
     *
     * @param bidId        投标ID
     * @param ProjectName  项目名称
     * @param deadlineTime 截止时间
     * @param receiverIds  接收人ID列表
     * @return 是否成功
     */
    @Transactional
    public boolean sendBatchBiddingReminder(String bidId, String ProjectName, String deadlineTime, List<String> receiverIds, String receiver) {
        // 参数校验
        if (StringUtils.isAnyBlank(bidId, ProjectName, deadlineTime) || receiverIds == null || receiverIds.isEmpty()) {
            log.error("批量发送投标提醒失败：参数不完整或接收人列表与ID列表数量不匹配");
            return false;
        }
        // 构建消息标题和内容
        String title = "投标即将截止提醒";
        String content = String.format("您有一条新的投标即将截止提醒：%s，截止时间：%s，请及时处理。", ProjectName, deadlineTime);

        return sendBatchMessage(title, content, "system", "system", bidId, receiverIds);
    }

    /**
     * 批量发送投标已截止提醒
     *
     * @param bidId        投标ID
     * @param ProjectName  项目名称
     * @param deadlineTime 截止时间
     * @param receiverIds  接收人ID列表
     * @return 是否成功
     */
    @Transactional
    public boolean afSendBatchBiddingReminder(String bidId, String ProjectName, String deadlineTime, List<String> receiverIds, String receiver) {
        // 参数校验
        if (StringUtils.isAnyBlank(bidId, ProjectName, deadlineTime) || receiverIds == null || receiverIds.isEmpty()) {
            log.error("批量发送投标提醒失败：参数不完整或接收人列表与ID列表数量不匹配");
            return false;
        }
        // 构建消息标题和内容
        String title = "投标已截止提醒";
        String content = String.format("您有一条新的投标已截止提醒：%s，截止时间：%s，请及时处理。", ProjectName, deadlineTime);

        return sendBatchMessage(title, content, "system", "system", bidId, receiverIds);
    }

    /**
     * 批量发送消息
     *
     * @param title        消息标题
     * @param content      消息内容
     * @param messageType  消息类型
     * @param businessType 业务类型
     * @param businessId   业务ID
     * @param receiverIds  接收人ID列表
     * @return 是否成功
     */
    @Override
    @Transactional
    public boolean sendBatchMessage(String title, String content, String messageType, String businessType,
                                    String businessId, List<String> receiverIds) {
        // 1. 参数校验
        if (StringUtils.isAnyBlank(title, content, messageType) ||
                receiverIds == null || receiverIds.isEmpty()) {
            log.error("批量发送消息参数校验失败：标题、内容、消息类型、发送人或接收人信息为空");
            return false;
        }

        // 5. 批量发送消息
        boolean allSuccess = true;
        int successCount = 0;
        int totalCount = receiverIds.size();

        for (int i = 0; i < totalCount; i++) {
            String receiverId = receiverIds.get(i);
            //根据receiverId从proc_user_supplier表中查询对应的username

            try {
                // 使用procUserSupplierRelationService根据userId查询用户名
                String receiver = procUserSupplierRelationService.getUsernameByUserId(receiverId);

                if (sendMessage(title, content, messageType, businessType, businessId, receiverId, receiver)) {
                    successCount++;
                } else {
                    allSuccess = false;
                    log.error("发送消息失败，接收人ID：{}", receiverId);
                }
            } catch (Exception e) {
                allSuccess = false;
                log.error("发送消息异常，接收人ID：{}", receiverId, e);
            }
        }

        log.info("批量发送消息完成，总计：{}，成功：{}，失败：{}", totalCount, successCount, totalCount - successCount);
        return allSuccess;
    }

    /**
     * 获取消息数量统计
     *
     * @param receiverId 接收人ID
     * @return 消息数量
     */
    @Override
    public int getMessageCount(String receiverId) {
        if (StringUtils.isBlank(receiverId)) {
            return 0;
        }
        return procurementMessageMapper.getMessageCountByReceiver(receiverId);
    }

    /**
     * 获取未读消息数量
     *
     * @param receiverId 接收人ID
     * @return 未读消息数量
     */
    @Override
    public int getUnreadMessageCount(String receiverId) {

        return procurementMessageMapper.getUnreadMessageCountByReceiver(receiverId);
    }

    /**
     * 根据消息类型获取消息
     *
     * @param messageType 消息类型
     * @param receiverId  接收人ID
     * @return 消息列表
     */

    public List<ProcurementMessage> getMessagesByType(String messageType, String receiverId) {
        if (StringUtils.isAnyBlank(messageType, receiverId)) {
            return new ArrayList<>();
        }
        return procurementMessageMapper.getMessagesByType(messageType, receiverId);
    }

    // 发送单条消息的通用方法 sendMessage方法发送通知，并返回发送结果
    private boolean sendMessage(String title, String content, String messageType, String businessType,
                                String businessId, String receiverId, String receiver) {
        ProcurementMessage message = new ProcurementMessage();
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String senderId = sysUser.getId();
        String sender = sysUser.getUsername();

        message.setTitle(title)
                .setContent(content)
                .setMessageType(messageType)
                .setBusinessType(businessType)
                .setBusinessId(businessId)
                .setSendType("1") // 系统消息
                .setSender(sender)
                .setReceiver(receiver)
                .setPriority(1)
                .setReadStatus("0") // 未读
                .setIsDeleted("0")
                .setCreateBy(sender)
                .setCreateTime(new Date())
                .setUpdateBy(sender)
                .setSenderId(senderId)
                .setReceiverId(receiverId)
                .setUpdateTime(new Date());
        try {
            // 推送WebSocket消息 todo
            this.sendToUser(receiverId,receiver, title, content, businessType, businessId);

            // 保存消息到数据库
            this.save(message);
            return true;
        } catch (Exception e) {
            log.error("发送消息失败", e);
            return false;
        }
    }

    // 获取投标类型名称
    private String getBidTypeName(String bidType) {
        // 根据实际字典配置返回对应的投标类型名称
        switch (bidType) {
            case "1":
                return "公开招标";
            case "2":
                return "邀请招标";
            case "3":
                return "竞争性谈判";
            case "4":
                return "单一来源";
            default:
                return "招标";
        }
    }

    @Override
    public boolean pushMessageToClient(String userId, ProcurementMessage message) {
        try {
            if (StringUtils.isBlank(userId) || message == null) {
                return false;
            }

            // 构建WebSocket消息格式
            JSONObject obj = new JSONObject();
            obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
            obj.put(WebsocketConst.MSG_TXT, message.getContent());
            obj.put("title", message.getTitle());
            obj.put("businessType", message.getBusinessType());
            obj.put("businessId", message.getBusinessId());
            obj.put("sendTime", message.getCreateTime());
            obj.put("msgId", message.getId());

            // 发送WebSocket消息
             WebSocketServer.sendMessageToUser(userId, obj.toJSONString());
            return true;
        } catch (Exception e) {
            log.error("【WebSocket推送】推送消息失败", e);
            return false;
        }
    }

    //TODO 未完成
    public void syncMessagesToClients(String[] userIds) {

    }

    //TODO 未完成
    public String sendAndPushMessage(String title, String content, String receiver, String businessType, String businessId) {
        return null;
    }


    public Result<?> sendToUser(String userId,String username, String title, String content, String businessType, String businessId) {
        try {
            // 构建WebSocket消息格式
            JSONObject obj = new JSONObject();
            obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
            obj.put(WebsocketConst.MSG_TXT, content);
            obj.put("usrname",username);
            obj.put("title", title);
            obj.put("businessType", businessType);
            obj.put("businessId", businessId);
            obj.put("sendTime", new Date());

            // 发送WebSocket消息
            boolean result = WebSocketServer.sendMessageToUser(userId, obj.toJSONString());
            log.info("【WebSocket推送】向用户 {} 推送消息: {}", userId, obj.toJSONString());
            return Result.OK("WebSocket消息发送成功!");
        } catch (Exception e) {
            log.error("【WebSocket推送】发送消息失败", e);
            return Result.error("WebSocket消息发送失败: " + e.getMessage());
        }
    }

    @Override
    public Result<?> sendToUsers(String userIds, String title, String content) {

        try {
            if (userIds == null || userIds.isEmpty()) {
                return Result.error("用户ID列表不能为空");
            }

            String[] userIdArray = userIds.split(",");

            // 构建WebSocket消息格式
            JSONObject obj = new JSONObject();
            obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
            obj.put(WebsocketConst.MSG_TXT, content);
            obj.put("title", title);
            obj.put("sendTime", new Date());

            // 发送WebSocket消息给多个用户
            WebSocketServer.sendMessageToUsers(userIdArray, obj.toJSONString());
            log.info("【WebSocket推送】向 {} 个用户发送消息: {}", userIdArray.length, obj.toJSONString());

            return Result.OK("WebSocket消息已发送!");
        } catch (Exception e) {
            log.error("【WebSocket推送】发送消息给多个用户失败", e);
            return Result.error("WebSocket消息发送失败: " + e.getMessage());
        }
    }

    @Override
    public Result<?> broadcast(String title, String content) {
        try {
            // 构建WebSocket消息格式
            JSONObject obj = new JSONObject();
            obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
            obj.put(WebsocketConst.MSG_TXT, content);
            obj.put("title", title);
            obj.put("sendTime", new Date());

            // 广播WebSocket消息
            WebSocketServer.sendMessageToAll(obj.toJSONString());
            log.info("【WebSocket推送】广播消息: {}", obj.toJSONString());

            return Result.OK("WebSocket消息广播成功!");
        } catch (Exception e) {
            log.error("【WebSocket推送】广播消息失败", e);
            return Result.error("WebSocket消息广播失败: " + e.getMessage());
        }
    }

    @Override
    public Result<?> sendAndPush(String title, String content, String receiverId, String businessType, String businessId) {
        try {
            // 保存消息到数据库并推送
            String messageId = sendAndPushMessage(title, content, receiverId, businessType, businessId);
            if (messageId != null) {
                return Result.OK("消息发送并推送成功!", messageId);
            } else {
                return Result.error("消息发送失败");
            }
        } catch (Exception e) {
            log.error("【消息发送】发送并推送消息失败", e);
            return Result.error("消息发送并推送失败: " + e.getMessage());
        }
    }

    @Override
    public void sendLotteryWinningMessage(String supplierId, String businessId) {
        try {
            // 创建消息记录
            ProcurementMessage message = new ProcurementMessage();
            LotteryManagement lotteryManagement = lotteryManagementService.getById(businessId);
            message.setBusinessId(businessId);
            message.setMessageType("2");
            message.setTitle("抽签中签通知");
            message.setContent("恭喜您在本次采购项目: "+ lotteryManagement.getProjectName()+" 抽签中成功中签，请及时关注后续流程安排。");
            message.setReadStatus("0"); // 0-未读，1-已读
            message.setCreateTime(new Date());
            message.setBusinessType("lottery");

            // 保存消息
            this.save(message);
            ProcUserSupplierRelation procUserSupplierRelation= procUserSupplierRelationService.getRelationBySearchKey(supplierId);
            this.sendMessage("抽签中签通知","恭喜您在本次采购项目: "+ lotteryManagement.getProjectName()+" 抽签中成功中签，请及时关注后续流程安排。","2",
                    "lottery",businessId,procUserSupplierRelation.getUserId(),procUserSupplierRelation.getUsername());
        } catch (Exception e) {
            log.error("发送抽签中签通知失败，供应商ID: {}, 业务ID: {}", supplierId, businessId, e);
        }
    }
}
